﻿using RimWorld;
using RimWorld.Planet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
using Verse.AI.Group;
using static System.Net.Mime.MediaTypeNames;

namespace SZ.Mech
{
    public static class MiaoUtility
    {
        
        private static List<List<Thing>> tempList = new List<List<Thing>>();
        public static void DropThingsNear(IntVec3 dropCenter, Map map, IEnumerable<Thing> things, int openDelay = 110, bool canInstaDropDuringInit = false, bool leaveSlag = false, bool canRoofPunch = true, bool forbid = true, bool allowFogged = true, Faction faction = null)
        {
            tempList.Clear();
            foreach (Thing thing in things)
            {
                List<Thing> list = new List<Thing>();
                list.Add(thing);
                tempList.Add(list);
            }
            DropThingGroupsNear(dropCenter, map, tempList, openDelay, canInstaDropDuringInit, leaveSlag, canRoofPunch, forbid, allowFogged, canTransfer: false, faction);
            tempList.Clear();
        }

        public static void DropThingGroupsNear(IntVec3 dropCenter, Map map, List<List<Thing>> thingsGroups, int openDelay = 110, bool instaDrop = false, bool leaveSlag = false, bool canRoofPunch = true, bool forbid = true, bool allowFogged = true, bool canTransfer = false, Faction faction = null)
        {
            foreach (List<Thing> thingsGroup in thingsGroups)
            {
                if (!DropCellFinder.TryFindDropSpotNear(dropCenter, map, out var result, allowFogged, canRoofPunch) && (canRoofPunch || !DropCellFinder.TryFindDropSpotNear(dropCenter, map, out result, allowFogged, canRoofPunch: true)))
                {
                    Log.Warning(string.Concat("DropThingsNear failed to find a place to drop ", thingsGroup.FirstOrDefault(), " near ", dropCenter, ". Dropping on random square instead."));
                    result = CellFinderLoose.RandomCellWith((IntVec3 c) => c.Walkable(map), map);
                }
                if (forbid)
                {
                    for (int i = 0; i < thingsGroup.Count; i++)
                    {
                        thingsGroup[i].SetForbidden(value: true, warnOnFail: false);
                    }
                }
                if (instaDrop)//下落位置？
                {
                    foreach (Thing item in thingsGroup)
                    {
                        GenPlace.TryPlaceThing(item, result, map, ThingPlaceMode.Near);
                    }
                    continue;
                }
                ActiveDropPodInfo activeDropPodInfo = new ActiveDropPodInfo();
                foreach (Thing item2 in thingsGroup)
                {
                    activeDropPodInfo.innerContainer.TryAdd(item2);
                }
                activeDropPodInfo.openDelay = openDelay;
                activeDropPodInfo.leaveSlag = leaveSlag;
                MakeDropPodAt(result, map, activeDropPodInfo, ThingDefOf.ActiveDropPod, ThingDefOf.DropPodIncoming);
            }
        }


        public static void DropThingsNearPro(IntVec3 dropCenter,int createRandomSize, Map map, IEnumerable<Thing> things, int openDelay = 110, bool canInstaDropDuringInit = false, bool leaveSlag = false, bool canRoofPunch = true, bool forbid = true, bool allowFogged = true, Faction faction = null)
        {
            tempList.Clear();
            foreach (Thing thing in things)
            {
                List<Thing> list = new List<Thing>();
                list.Add(thing);
                tempList.Add(list);
            }
            DropThingGroupsNearPro(dropCenter, map, tempList, createRandomSize, new IntVec2(4,4) , openDelay, canInstaDropDuringInit, leaveSlag, canRoofPunch, forbid, allowFogged, canTransfer: false, faction);
            tempList.Clear();
        }

        public static void DropThingGroupsNearPro(IntVec3 dropCenter, Map map, List<List<Thing>> thingsGroups,int createRandomSize, IntVec2 size, int openDelay = 110, bool instaDrop = false, bool leaveSlag = false, bool canRoofPunch = true, bool forbid = true, bool allowFogged = true, bool canTransfer = false, Faction faction = null)
        {

            int  nextChange = 0;
            if(createRandomSize < 2)
            {
                createRandomSize = 2;
            }

            foreach (List<Thing> thingsGroup in thingsGroups)
            {
                IntVec3 result = new IntVec3();
                int x =  UnityEngine.Random.Range(1, createRandomSize);
                int z = UnityEngine.Random.Range(1, createRandomSize);
                if (nextChange == 1)
                {

                }
                else if (nextChange==2)
                {
                    x = -x;
                }
                else if (nextChange == 3)
                {
                    z = -z;
                }
                else if (nextChange == 4)
                {
                    x = -x;
                    z = -z;
                    nextChange = 0;
                }
                nextChange++;

                result.x = (x* size.x) + dropCenter.x;
                result.z = (z * size.z) + dropCenter.z;

                //if (!DropCellFinder.TryFindDropSpotNear(dropCenter, map, out var result, allowFogged, canRoofPunch,true,new IntVec2(5,5),false))
                //{
                //    //DropThingsNearPro找不到放置位置
                //    //Log.Warning(string.Concat("DropThingsNearPro failed to find a place to drop ", thingsGroup.FirstOrDefault(), " near ", dropCenter, ". Dropping on random square instead."));

                //    result = CellFinderLoose.RandomCellWith((IntVec3 c) => c.Walkable(map), map,1);//获得一个可以用的点
                //}
                if (forbid)
                {
                    for (int i = 0; i < thingsGroup.Count; i++)
                    {
                        thingsGroup[i].SetForbidden(value: true, warnOnFail: false);
                    }
                }
                if (instaDrop)//下落位置？
                {
                    foreach (Thing item in thingsGroup)
                    {
                        GenPlace.TryPlaceThing(item, result, map, ThingPlaceMode.Near);
                    }
                    continue;
                }
                ActiveDropPodInfo activeDropPodInfo = new ActiveDropPodInfo();
                foreach (Thing item2 in thingsGroup)
                {
                    activeDropPodInfo.innerContainer.TryAdd(item2);
                }
                activeDropPodInfo.openDelay = openDelay;
                activeDropPodInfo.leaveSlag = leaveSlag;
                MakeDropPodAt(result, map, activeDropPodInfo, ThingDefOf.ActiveDropPod, ThingDefOf.DropPodIncoming);
            }
        }

        public static void TryLaunch(Pawn caster, DragonFlyExtension dragonFlyExtension, int destinationTile, TransportPodsArrivalAction arrivalAction)
        {
            if (!caster.Spawned)
            {
                Log.Error(string.Concat("Tried to launch ", caster, ", but it's unspawned."));
                return;
            }
            Map map = caster.Map;

            ActiveDropPod activeDropPod = (ActiveDropPod)ThingMaker.MakeThing(dragonFlyExtension.activeDropPodFly);//行动吊舱
                                                                                                                   //ActiveDropPod activeDropPod = (ActiveDropPod)ThingMaker.MakeThing(SZ_DefOf.SZ_DragonFlyA);//行动吊舱
            activeDropPod.Contents = new ActiveDropPodInfo();
            caster.DeSpawn(DestroyMode.Vanish);

            activeDropPod.Contents.innerContainer.TryAddOrTransfer(caster, true);

            FlyShipLeaving obj = (FlyShipLeaving)SkyfallerMaker.MakeSkyfaller(dragonFlyExtension.dropPodLeavingFly, activeDropPod);//飞行中的效果
                                                                                                                                   //FlyShipLeaving obj = (FlyShipLeaving)SkyfallerMaker.MakeSkyfaller(SZ_DefOf.DropPodLeavingDragonFlyA, activeDropPod);//飞行中的效果

            obj.groupID = Find.UniqueIDsManager.GetNextTransporterGroupID();//可能可以这样写
            obj.destinationTile = destinationTile;
            obj.arrivalAction = arrivalAction;//到达行动
            obj.worldObjectDef = WorldObjectDefOf.TravelingTransportPods;
            GenSpawn.Spawn(obj, caster.Position, map);
        }


        public static void DropTravelingTransportPods(List<ActiveDropPodInfo> dropPods, IntVec3 near, Map map,ThingDef activeDropPodDef, ThingDef dropPodIncomingDef)
        {
            TransportPodsArrivalActionUtility.RemovePawnsFromWorldPawns(dropPods);
            for (int i = 0; i < dropPods.Count; i++)
            {
                DropCellFinder.TryFindDropSpotNear(near, map, out var result, allowFogged: false, canRoofPunch: true);
                MakeDropPodAt(result, map, dropPods[i], activeDropPodDef, dropPodIncomingDef);
            }
        }

        public static void MakeDropPodAt(IntVec3 c, Map map, ActiveDropPodInfo info, ThingDef activeDropPodDef,ThingDef dropPodIncomingDragonDef, Faction faction = null)
        {
            ActiveDropPod activeDropPod = (ActiveDropPod)ThingMaker.MakeThing(activeDropPodDef);
            activeDropPod.Contents = info;
            SkyfallerMaker.SpawnSkyfaller(dropPodIncomingDragonDef, activeDropPod, c, map);
            //SkyfallerMaker.SpawnSkyfaller(SZ_DefOf.DropPodIncomingDragonFlyA, activeDropPod, c, map);
            //Lord lord = LordMaker.MakeNewLord(faction, new LordJob_AssaultColony(), map);

            foreach (Thing item in (IEnumerable<Thing>)activeDropPod.Contents.innerContainer)
            {
                Pawn pawn;
                if ((pawn = item as Pawn) != null && pawn.IsWorldPawn())
                {
                    Find.WorldPawns.RemovePawn(pawn);
                    pawn.psychicEntropy?.SetInitialPsyfocusLevel();
                    //lord.AddPawn(pawn);
                }
            }
        }


        /// <summary>
        /// 溅射8个目标
        /// </summary>
        /// <param name="caster"></param>
        /// <param name="target"></param>
        /// <param name="damageInfo"></param>
        public static void TargetSputtering8(Pawn caster,LocalTargetInfo target, DamageInfo damageInfo,Action<Pawn> OnTarget)
        {
            for (int i = 0; i < 8; i++)
            {
                IntVec3 c = target.Cell + GenAdj.AdjacentCells[i];
                Pawn pawn = GetFirstPawnNotDeadOrDowned(c, caster.Map);
                if (pawn != null && pawn.Faction != caster.Faction)
                {
                    pawn.TakeDamage(damageInfo);
                    DrawCleaving(pawn, caster);
                    OnTarget?.Invoke(pawn);
                }
            }
            {
                IntVec3 c1 = target.Cell + new IntVec3(0, 0, 2);
                Pawn pawn = GetFirstPawnNotDeadOrDowned(c1, caster.Map);
                if (pawn != null && pawn.Faction != caster.Faction)
                {
                    pawn.TakeDamage(damageInfo);
                    DrawCleaving(pawn, caster);
                    OnTarget?.Invoke(pawn);
                }
                IntVec3 c2 = target.Cell + new IntVec3(0, 0, -2);
                pawn = GetFirstPawnNotDeadOrDowned(c2, caster.Map);
                if (pawn != null && pawn.Faction != caster.Faction)
                {
                    pawn.TakeDamage(damageInfo);
                    DrawCleaving(pawn, caster);
                    OnTarget?.Invoke(pawn);
                }
                IntVec3 c3 = target.Cell + new IntVec3(2, 0, 0);
                pawn = GetFirstPawnNotDeadOrDowned(c3, caster.Map);
                if (pawn != null && pawn.Faction != caster.Faction)
                {
                    pawn.TakeDamage(damageInfo);
                    DrawCleaving(pawn, caster);
                    OnTarget?.Invoke(pawn);
                }
                IntVec3 c4 = target.Cell + new IntVec3(-2, 0, 0);
                pawn = GetFirstPawnNotDeadOrDowned(c4, caster.Map);
                if (pawn != null && pawn.Faction != caster.Faction)
                {
                    pawn.TakeDamage(damageInfo);
                    DrawCleaving(pawn, caster);
                    OnTarget?.Invoke(pawn);
                }
            }
        }

        public static Pawn GetFirstPawnNotDeadOrDowned(IntVec3 c, Map map)
        {
            List<Thing> thingList = GridsUtility.GetThingList(c, map);
            for (int i = 0; i < thingList.Count; i++)
            {
                if (thingList[i] is Pawn pawn)
                {
                    bool flag = pawn != null && !pawn.Dead && !pawn.Downed;
                    if (flag)
                    {
                        return pawn;
                    }
                }
            }
            return null;
         }

        public static void DrawCleaving(Pawn cleavedPawn, Pawn caster)
        {
            if (!caster.Dead && !caster.Downed)
            {
                bool flag2 = GenView.ShouldSpawnMotesAt(caster.Position, caster.Map, true) && !caster.Map.moteCounter.Saturated;
                if (flag2)
                {
                    float num = (float)(caster.Position.x - cleavedPawn.Position.x);
                    float x = (float)(caster.Position.z - cleavedPawn.Position.z);
                    bool flag3 = Mathf.Sqrt(Mathf.Pow(num, 2f) + Mathf.Pow(num, 2f)) > 1f;
                    if (flag3)
                    {
                        float num2 = Mathf.Atan2(num, x) * 180f / 3.1415927f;
                        //Vector3 b = cleavedPawn.Position.ToVector3();

                        Mote moteThrown = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_Stun);
                        moteThrown.Attach(cleavedPawn);
                        GenSpawn.Spawn(moteThrown, caster.Position, caster.Map, 0);
                    }
                }
            }
        }


    }
}
